package JackSu.java01;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

//生产者消费者，多生产多消费
public class ProducerConsumerDemo {

    private String name;
    private int count = 1;
    private boolean flag = false;
    private Lock lock = new ReentrantLock();
    private Condition producerCon = lock.newCondition();//生产监视器，用于唤醒消费者线程
    private Condition consumerCon = lock.newCondition();//消费监视器，用于唤醒生产者线程

    public/* synchronized*/ void set(String name){
        lock.lock();
        try {
        /*if*/while(flag){
                /*try {
                    this.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }*/
                producerCon.await();
            }
            this.name = name + count++;
            flag = true;
            System.out.println(Thread.currentThread().getName()+"...生产者..."+this.name);
            /*notify();*/
            /*notifyAll();*/
            consumerCon.signal();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    public/* synchronized*/ void out(){
        lock.lock();
        try {
    /*if*/while(!flag){
                /*try {
                    this.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }*/
                consumerCon.await();
            }
            flag = false;
            System.out.println(Thread.currentThread().getName()+"...消费者......"+this.name);
            /*notify();*/
            /*notifyAll();*/
            producerCon.signal();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    static class Producer implements Runnable{
        private ProducerConsumerDemo r;
        Producer(ProducerConsumerDemo r){
            this.r = r;
        }

        @Override
        public void run() {
            while (true) {
                r.set("西瓜");
            }
        }
    }

    static class Consumer implements Runnable{
        private ProducerConsumerDemo r;
        Consumer(ProducerConsumerDemo r){
            this.r = r;
        }

        @Override
        public void run() {
            while(true){
                r.out();
            }
        }
    }

    public static void main(String[] args) {
        ProducerConsumerDemo demo = new ProducerConsumerDemo();
        Producer producer = new Producer(demo);
        Consumer consumer = new Consumer(demo);
        Thread thread1 = new Thread(producer);
        Thread thread2 = new Thread(producer);
        Thread thread3 = new Thread(consumer);
        Thread thread4 = new Thread(consumer);
        thread1.start();
        thread2.start();
        thread3.start();
        thread4.start();
    }
}
